package dataImport.action;

import java.util.HashMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import dataImport.action.abstracts.AbstractEntityReader;
import dataImport.action.abstracts.AbstractTempEntityReader;
import dataImport.action.helper.UnityGuardian;
import dataImport.action.manager.EntityReaderManager;
import dataImport.action.manager.storage.EntityReaderStorageKey;
import dataImport.exception.DuplicateAttributeException;
import dataImport.exception.MissingAttributeException;
import dataImport.exception.MissingReader;
import dataImport.exception.NoEntityRelatedWithException;
import dataImport.exception.UniquenessRestrictionViolatedException;
import dataImport.model.CustomAction;
import dataImport.model.EmoteBeforeAction;
import dataImport.model.EmoteBeforeActionTemp;
import dataImport.model.abstracts.AbstractEntity;


public class EmoteBeforeActionReader extends AbstractTempEntityReader {

	private static final long serialVersionUID = -1054336388689621585L;

	public static final String ENTITY_NAME = "emoteBeforeAction";

	private static final String ATTRIBUTE_VALUE = "value";

	private UnityGuardian customActionId;

	public EmoteBeforeActionReader() {
		super();
		this.customActionId = new UnityGuardian();
	}

	@Override
	protected void checkRequiredReaders(final EntityReaderManager entityReaderManager) throws MissingReader {
		entityReaderManager.contains(EntityReaderStorageKey.CUSTOM_ACTION);
		entityReaderManager.getCustomActionReader().isFixed();
	}

	@Override
	protected AbstractEntity createEntity(Element element) {
		final String value = element.getAttribute(ATTRIBUTE_VALUE);
		final Element parentNode = (Element) element.getParentNode();
		final String parentNodeName = parentNode.getNodeName();
		final String parentNodeId = parentNode.getAttribute(AbstractEntityReader.ATTRIBUTE_ID);

		this.verifyRestrictions(parentNodeName, parentNodeId, value);

		return new EmoteBeforeActionTemp(parentNodeId, value);
	}

	@Override
	protected void fixEntities(final HashMap<String, AbstractEntity> newEntities, final EntityReaderManager entityReaderManager) throws MissingReader {
		final CustomActionReader customActionReader = entityReaderManager.getCustomActionReader();

		for (final AbstractEntity abstractEntity : this.abstractEntities.values()) {
			final EmoteBeforeActionTemp emoteBeforeActionTemp = (EmoteBeforeActionTemp) abstractEntity;

			final String customActionId = emoteBeforeActionTemp.getCustomActionId();
			final String text = emoteBeforeActionTemp.getText();

			final CustomAction customAction = (CustomAction) customActionReader.getEntityWithId(customActionId);

			newEntities.put(AbstractEntity.createId(customActionId, text), new EmoteBeforeAction(customAction, text));
		}
	}

	@Override
	public void read(Document document) {
		this.read(EmoteBeforeActionReader.ENTITY_NAME, document);
	}

	private void verifyRestrictions(final String customActionName, final String customActionId, final String text) {
		if (text.isEmpty()) {
			throw new MissingAttributeException(ATTRIBUTE_VALUE);
		}

		try {
			this.customActionId.ensureUniqueness(customActionId);
		}
		catch (final UniquenessRestrictionViolatedException e) {
			throw new DuplicateAttributeException(EmoteBeforeActionReader.ENTITY_NAME, customActionId);
		}

		if (!customActionName.equals(CustomActionReader.ENTITY_NAME)) {
			throw new NoEntityRelatedWithException(EmoteBeforeActionReader.ENTITY_NAME, CustomActionReader.ENTITY_NAME);
		}
	}
}
